﻿'=====================================================================
'模 块 名：Database

'描    述：数据库操作

'依赖模块：System.Data.OleDb

'原始版本：1.00
'作    者：刘德亮
'完成日期：2020-3-11

'修改版本：1.01
'修改作者：刘德亮
'修改日期：2020-6-17
'修改记录：数据库规划：全局设定、用户管理、产品管理、报告管理、测试记录

'修改版本：1.02
'修改作者：刘德亮
'修改日期：2020-7-10
'修改记录：频繁读写数据库时太慢(每次都要重新打开数据库)，将数据库连接运行时保持
'修改作者：刘德亮
'修改日期：2020-7-21
'修改记录：Product添加"SNG上限_单机气密","SNG下限_单机气密"，"时间_小漏_容积检测","时间_大漏_TANK调平衡"
'修改作者：刘德亮
'修改日期：2020-7-23
'修改记录：Product添加"MS计算用参数",添加PublicData
'修改作者：刘德亮
'修改日期：2020-10-7
'修改记录：弹出错误时，错误源按用户的角度描述
'修改日期：2021-6-7
'修改记录：数据库加密码调用

'修改版本：1.03
'修改日期：2021-12-29
'修改作者：刘德亮
'修改记录：
'1.按编程规范整理代码格式等，功能不变:
'  变量前缀、ByVal缺省、
'
'版本历史：见《版本历史.txt》

'=====================================================================
Imports System.Data
Imports System.Data.OleDb
Imports System.IO
Imports FL_8x0.FL_830.Model
Imports FL_8x0.Model
Imports FL_8x0.View
Imports GalaSoft.MvvmLight.Messaging

Namespace FL_8x0.Common

    Public Module Database
        Public Structure MotorData '步进电机参数
            Dim sngCAL电机步长 As Single        'mm
            Dim sngCAL电机步距角 As Single      '°
            Dim sngCAL活塞半径 As Single        'mm
            Dim sngCAL活塞长度 As Single        'mm
            Dim sngCAL最小容积 As Single        'mL
            Dim sngCAL距离校准系数 As Single    '
            Dim sngCAL运行速度 As Single        'mm/s
            Dim sngCAL差压上限 As Single        'Pa

            Dim sngTANK电机步长 As Single       'mm
            Dim sngTANK电机步距角 As Single     '°
            Dim sngTANK活塞半径 As Single       'mm
            Dim sngTANK活塞长度 As Single       'mm
            Dim sngTANK最小容积 As Single       'mL
            Dim sngTANK距离校准系数 As Single   '
            Dim sngTANK运行速度 As Single       'mm/s
        End Structure

        Public Structure PublicData '通用设置参数
            '用户设定
            Dim uint直压_Point As UInt16    '直压格式索引(0-*)

            Dim uint漏率_Point As UInt16    '漏率小数点格式索引(0-*)

            Dim blnAutoSaveWave As Boolean      '曲线是否自动保存
            Dim strAutoSaveWavePath As String   '曲线自动保存目录

            Dim blnAutoAxisY As Boolean      '曲线直压Y轴自动伸缩
            Dim sngMaxAxisY As Single        'Y轴最大
            Dim sngMinAxisY As Single        'Y轴最小

            Dim blnAutoAxisY2 As Boolean     '曲线差压Y轴自动伸缩
            Dim sngMaxAxisY2 As Single       'Y2轴最大
            Dim sngMinAxisY2 As Single       'Y2轴最小

            Dim blnScanGuns As Boolean       '启用扫码枪
            Dim blnAutoStart As Boolean      '扫码后自动启动
            Dim blnWriteToMachine As Boolean  '条码写入检漏仪
            Dim uintPortName As UShort        '串口号 
            Dim uintBaudRate As UShort        '波特率
            Dim uintEndChar As UShort         '结尾字符

            Dim strUserName As String
            Dim strPassword As String
            Dim blnAuditMode As Boolean

            Dim blnEnableReadPresssure As Boolean

            '报表输出设定
            Dim strTestRecordSavePath As String         '测试记录报表保存目录
            Dim strTestRecordTemplateName As String     '使用测试记录模板名称

            '出厂设定
            Dim sngMaxGP As Single      '最大直压
            Dim sngMinGP As Single      '最小直压
        End Structure

        Public g_udtOtherSet As New PublicData   '全局变量(通用设置参数)


        Public g_udtReport As New ReportModel    '全局变量(当前测试报告)

        Public g_udtProduct As New ProductModel   '全局变量(当前产品设定)


        '模板管理
        Public Structure TestRecordTemplate '测试记录模板
            Dim strTemplateName As String   '模板名称
            Dim strSheetName As String      'Sheet名称

            Dim str报告号 As String

            Dim str产品号 As String
            Dim str产品名称 As String
            Dim str产品型号 As String

            Dim str产品编码 As String
            Dim strMS检漏环节 As String
            Dim str日期时间 As String
            Dim str用户名 As String

            Dim str小漏结果 As String
            Dim str大漏结果 As String
            Dim str漏率结果 As String
            Dim str孔径结果 As String
            Dim str启动时气源压力 As String
            Dim str平衡1被测物压力 As String
            Dim str测试压单位 As String
            Dim str充气2结束差压 As String
            Dim str平衡2结束差压 As String
            Dim str小漏结束温度 As String
            Dim str结果环节 As String
            Dim str结果判定 As String
            Dim str错误号 As String
            Dim str检测类型 As String
            Dim str容积检测结果 As String

            Dim str时间_充气2 As String
            Dim str时间_平衡1 As String
            Dim str时间_平衡2 As String
            Dim str时间_小漏 As String
            Dim str时间_大漏 As String
            Dim str时间_排气 As String

            Dim str时间_小漏_容积检测 As String   '缝隙容积检测

            Dim str时间_大漏_TANK调平衡 As String   'TANK调平衡

            Dim str测试压 As String
            Dim str充气2上限 As String
            Dim str充气2下限 As String
            Dim strBNG上限 As String
            Dim strBNG下限 As String
            Dim strSNG上限 As String
            Dim strSNG下限 As String
            Dim strLNG上限 As String
            Dim strLNG下限 As String
            Dim strNG上限 As String
            Dim strNG下限 As String

            Dim strSNG上限_单机气密 As String
            Dim strSNG下限_单机气密 As String

            Dim str小漏修正模式 As String
            Dim str小漏偏倚值 As String
            Dim str小漏修正系数 As String

            Dim str大漏修正模式 As String
            Dim str大漏偏倚值 As String
            Dim str大漏修正系数 As String

            'MS计算用参数
            Dim str缝隙容积 As String   '小漏缝隙容积(mL)(含检漏仪内容积、气管、夹具缝隙容积)
            Dim strTANK容积 As String   '大漏TANK容积(mL)(含TANK气管、TANK罐容积)
            Dim str被测物空心容积 As String  '被测物空心容积(mL)
        End Structure


        '全局变量
        Dim g_dbConn用户设定 As OleDbConnection
        Dim g_dbConn出厂设定 As OleDbConnection
        Public g_dbConn测试记录 As OleDbConnection
        Dim g_dbConn模板管理 As OleDbConnection


        Public Function ReopenDataBase(strProvider As String, strPath As String, strUserName As String, strPassword As String) As Boolean
            Dim strConn As String
            Try
                If Not IsNothing(g_dbConn测试记录) Then
                    g_dbConn测试记录.Close()

                    If File.Exists(strPath & "\测试记录.mdb") Then
                        strConn = "Provider=" & strProvider & ";Data Source=" & strPath & "\测试记录.mdb" &
                                  ";Persist Security Info=False;Jet OLEDB:Database Password=" & strUserName & strPassword
                        g_dbConn测试记录 = New OleDbConnection(strConn)
                        g_dbConn测试记录.Open()
                    End If
                End If

                If Not IsNothing(g_dbConn模板管理) Then
                    g_dbConn模板管理.Close()
                    If File.Exists(strPath & "\模板管理.mdb") Then
                        strConn = "Provider=" & strProvider & ";Data Source=" & strPath & "\模板管理.mdb" &
                                  ";Persist Security Info=False;Jet OLEDB:Database Password=" & strUserName & strPassword
                        g_dbConn模板管理 = New OleDbConnection(strConn)
                        g_dbConn模板管理.Open()
                    End If
                End If
            Catch ex As Exception
                log.WriteLogError("OpenDatabase()", ex.Message)
                Return False
            End Try

            Return True
        End Function


        '=====================================================================
        '函 数 名: MakeNewID
        '参    数: 
        '返 回 值: 产品号
        '功能描述: 按当前日期时间生成产品号(唯一)
        '=====================================================================
        Public Function MakeNewID() As String
            Dim strID As String = ""
            Dim strTmp As String = ""

            Try
                strTmp = CStr(Now.Year()) '年
                While strTmp.Length < 4
                    strTmp = "0" & strTmp
                End While

                strID &= strTmp

                strTmp = CStr(Now.Month()) '月
                While strTmp.Length < 2
                    strTmp = "0" & strTmp
                End While

                strID &= strTmp

                strTmp = CStr(Now.Day()) '日
                While strTmp.Length < 2
                    strTmp = "0" & strTmp
                End While

                strID &= strTmp

                strTmp = CStr(Now.Hour()) '时
                While strTmp.Length < 2
                    strTmp = "0" & strTmp
                End While

                strID &= strTmp

                strTmp = CStr(Now.Minute()) '分
                While strTmp.Length < 2
                    strTmp = "0" & strTmp
                End While

                strID &= strTmp

                strTmp = CStr(Now.Second()) '秒
                While strTmp.Length < 2
                    strTmp = "0" & strTmp
                End While

                strID &= strTmp '& "0"

            Catch ex As Exception
                log.WriteLogError("MakeNewID()", ex.Message)
            End Try

            Return strID
        End Function


        '=====================================================================
        '函 数 名: OpenDatabase
        '参    数: strProvider = 数据库接口
        '          strPath = 数据库目录
        '          strUserName = 数据库用户名
        '          strPassword = 数据库密码
        '返 回 值: false = 错误，true = 正确
        '功能描述: 初始化连接数据库，并保持连接以便高效率
        '=====================================================================
        Public Function OpenDatabase(strProvider As String, strPath As String, strUserName As String, strPassword As String) _
            As Boolean
            Dim strConn As String

            Try
                If IsNothing(g_dbConn出厂设定) Then
                    If File.Exists(strPath & "\出厂设定.mdb") Then
                        strConn = "Provider=" & strProvider & ";Data Source=" & strPath & "\出厂设定.mdb" &
                                  ";Persist Security Info=False;Jet OLEDB:Database Password=" & strUserName & strPassword
                        g_dbConn出厂设定 = New OleDbConnection(strConn)
                        g_dbConn出厂设定.Open()
                    End If
                End If

                If IsNothing(g_dbConn用户设定) Then
                    If File.Exists(strPath & "\用户设定.mdb") Then
                        strConn = "Provider=" & strProvider & ";Data Source=" & strPath & "\用户设定.mdb" &
                                  ";Persist Security Info=False;Jet OLEDB:Database Password=" & strUserName & strPassword
                        g_dbConn用户设定 = New OleDbConnection(strConn)
                        g_dbConn用户设定.Open()
                    End If
                End If

                If IsNothing(g_dbConn测试记录) Then
                    If File.Exists(strPath & "\测试记录.mdb") Then
                        strConn = "Provider=" & strProvider & ";Data Source=" & strPath & "\测试记录.mdb" &
                                  ";Persist Security Info=False;Jet OLEDB:Database Password=" & strUserName & strPassword
                        g_dbConn测试记录 = New OleDbConnection(strConn)
                        g_dbConn测试记录.Open()
                    End If
                End If

                If IsNothing(g_dbConn模板管理) Then
                    If File.Exists(strPath & "\模板管理.mdb") Then
                        strConn = "Provider=" & strProvider & ";Data Source=" & strPath & "\模板管理.mdb" &
                                  ";Persist Security Info=False;Jet OLEDB:Database Password=" & strUserName & strPassword
                        g_dbConn模板管理 = New OleDbConnection(strConn)
                        g_dbConn模板管理.Open()
                    End If
                End If

            Catch ex As Exception
                log.WriteLogError("OpenDatabase()", ex.Message)
                Return False
            End Try

            Return True
        End Function


        '=====================================================================
        '函 数 名: CloseDatabase
        '参    数: 
        '返 回 值: false = 错误，true = 正确
        '功能描述: 关闭数据库连接
        '=====================================================================
        Public Function CloseDatabase() As Boolean
            Try
                If Not IsNothing(g_dbConn出厂设定) Then
                    g_dbConn出厂设定.Close()
                    g_dbConn出厂设定 = Nothing
                End If

                If Not IsNothing(g_dbConn用户设定) Then
                    g_dbConn用户设定.Close()
                    g_dbConn用户设定 = Nothing
                End If

                If Not IsNothing(g_dbConn测试记录) Then
                    g_dbConn测试记录.Close()
                    g_dbConn测试记录 = Nothing
                End If

                If Not IsNothing(g_dbConn模板管理) Then
                    g_dbConn模板管理.Close()
                    g_dbConn模板管理 = Nothing
                End If

            Catch ex As Exception
                log.WriteLogError("CloseDatabase()", ex.Message)
                Return False
            End Try

            Return True
        End Function


        '=====================================================================
        '函 数 名: Read_PublicSet
        '参    数: 
        '返 回 值: 
        '功能描述: 读取[全局设定]
        '=====================================================================
        Public Sub Read_PublicSet()
            Try
                '用户设定

                g_udtOtherSet.uint直压_Point = User_ReadPublicValue("压力小数点", "1") '1="0.0"

                g_udtOtherSet.uint漏率_Point = User_ReadPublicValue("漏率小数点", "2") '2="0.00E+0"

                g_udtOtherSet.blnAutoSaveWave = User_ReadPublicValue("自动保存曲线", False)
                g_udtOtherSet.strAutoSaveWavePath = User_ReadPublicValue("曲线自动保存目录", g_strStartupPath & "\")

                g_udtOtherSet.blnAutoAxisY = User_ReadPublicValue("曲线差压Y轴自动伸缩", False)
                g_udtOtherSet.sngMaxAxisY = User_ReadPublicValue("Y轴最大", "100")
                g_udtOtherSet.sngMinAxisY = User_ReadPublicValue("Y轴最小", "-100")

                g_udtOtherSet.blnAutoAxisY2 = User_ReadPublicValue("曲线直压Y轴自动伸缩", False)
                g_udtOtherSet.sngMaxAxisY2 = User_ReadPublicValue("Y2轴最大", "100")
                g_udtOtherSet.sngMinAxisY2 = User_ReadPublicValue("Y2轴最小", "-100")


                g_udtOtherSet.blnScanGuns = User_ReadPublicValue("扫描枪有效", False)
                g_udtOtherSet.blnAutoStart = User_ReadPublicValue("扫描后自动启动", False)
                g_udtOtherSet.blnWriteToMachine = User_ReadPublicValue("条码写入仪器", False)
                g_udtOtherSet.uintBaudRate = User_ReadPublicValue("扫描枪_波特率", "3")
                g_udtOtherSet.uintPortName = User_ReadPublicValue("扫描枪_串口号", "1")
                g_udtOtherSet.uintEndChar = User_ReadPublicValue("扫描枪_结尾", "2")

                g_udtOtherSet.strUserName = User_ReadPublicValue("默认用户名", "")
                g_udtOtherSet.strPassword = User_ReadPublicValue("默认密码", "")
                g_udtOtherSet.blnAuditMode = User_ReadPublicValue("审计模式", False)

                g_udtOtherSet.blnEnableReadPresssure = User_ReadPublicValue("准备环节读取直压", False)

                '报表管理
                g_udtOtherSet.strTestRecordSavePath = User_ReadPublicValue("测试记录保存目录", "C:\TestRecord\")   '测试记录报表保存目录
                g_udtOtherSet.strTestRecordTemplateName = User_ReadPublicValue("测试记录模板名称", "Excel检测报告模板2.xlsx")
                '使用测试记录模板名称
                TestReportUpdate(g_udtOtherSet.strTestRecordTemplateName)


            Catch ex As Exception
                log.WriteLogError("Read_PublicSet()", ex.Message)
            End Try
        End Sub


        '=====================================================================
        '函 数 名: User_ReadPublicValue
        '参    数: strName = 变量名
        '          strDefault = 默认值
        '返 回 值: 变量值
        '功能描述: 读取[用户设定.mdb]的[全局设定]，读出指定变量值
        '=====================================================================
        Public Function User_ReadPublicValue(strName As String, strDefault As String) As String
            If strName = "" Then
                log.WriteLogAssert("读用户通用设定", "strName=空")
                Return ""
            End If

            'If strDefault = "" Then
            '    log.WriteLogAssert("读用户通用设定", "strDefault=空")
            '    Return ""
            'End If

            Dim strResult As String = strDefault

            If Not IsNothing(g_dbConn用户设定) Then
                Dim strCmd As String = "Select * FROM 全局设定 WHERE 名称 = '" & strName & "'"

                Dim dbAdapter As New OleDbDataAdapter
                Dim dbTable As New DataTable

                Try
                    dbAdapter = New OleDbDataAdapter(strCmd, g_dbConn用户设定) '打开数据库

                    dbAdapter.Fill(dbTable) '提取数据

                    If dbTable.Rows.Count > 0 Then
                        If dbTable.Rows.Item(0).Item("名称") = strName Then
                            strResult = dbTable.Rows.Item(0).Item("值")
                        End If
                    End If

                Catch ex As Exception
                    log.WriteLogDebug("读用户通用设定:" & strName, ex.Message)
                Finally
                    dbAdapter.Dispose()
                    dbTable = Nothing
                    dbAdapter = Nothing
                End Try

            End If

            If strResult = "空" Then
                strResult = ""
            End If

            Return strResult
        End Function


        '=====================================================================
        '函 数 名: User_AddPublicValue
        '参    数: strName = 变量名
        '          strValue = 默认值
        '          strReason = 修改原因
        '返 回 值: 
        '功能描述: 添加[用户设定.mdb]的[全局设定]
        '=====================================================================
        Private Sub User_AddPublicValue(strName As String, strValue As String, strReason As String)
            If strName = "" Then
                log.WriteLogAssert("添加用户通用设定", "strName=空")
                Return
            End If

            If strValue = "" Then
                strValue = "空"
            End If

            If Not IsNothing(g_dbConn用户设定) Then
                Dim strInfo As String = "{" & strName & "=" & strValue & "}"
                log.WriteLogInfo("添加用户通用设定", "{" & "添加原因=" & strReason & ", " & strInfo & "}")

                Dim strCmd As String = "INSERT INTO 全局设定 ( [名称], [值] ) "
                strCmd &= "VALUES ( '" & strName & "', '" & strValue & "' )"

                Dim dbCmd As New OleDbCommand(strCmd, g_dbConn用户设定)

                Try
                    dbCmd.ExecuteNonQuery()
                Catch ex As Exception
                    log.WriteLogDebug("添加用户通用设定:" & strName & "," & strValue, ex.Message)
                Finally
                    dbCmd = Nothing
                End Try

            End If

            Return
        End Sub


        '=====================================================================
        '函 数 名: User_EditPublicValue
        '参    数: strName = 变量名
        '          strValue = 默认值
        '          strReason = 修改原因
        '返 回 值: 
        '功能描述: 更新[用户设定.mdb]的[全局设定]
        '=====================================================================
        Private Sub User_EditPublicValue(strName As String, strValue As String, strReason As String)
            If strName = "" Then
                log.WriteLogAssert("修改用户通用设定", "strName=空")
                Return
            End If

            If strValue = "" Then
                strValue = "空"
            End If

            Dim strValue_pre As String = User_ReadPublicValue(strName, "未发现变量")

            If strValue_pre = "未发现变量" Then
                Return '未发现变量
            End If

            If strValue_pre = strValue Then
                Return '未修改，不更新
            End If

            If Not IsNothing(g_dbConn用户设定) Then
                Dim strInfo_pre As String = "{" & strName & "=" & strValue_pre & "}"
                Dim strInfo As String = "{" & strName & "=" & strValue & "}"
                log.WriteLogInfo("修改用户通用设定", "{" & "修改原因=" & strReason & "," & strInfo_pre & " 变为 " & strInfo & "}")

                Dim strCmd As String = "UPDATE 全局设定 SET 值 = '" & strValue & "' "
                strCmd &= "WHERE 名称 = '" & strName & "'"

                Dim dbCmd As New OleDbCommand(strCmd, g_dbConn用户设定)

                Try
                    dbCmd.ExecuteNonQuery()
                Catch ex As Exception
                    log.WriteLogDebug("修改用户通用设定:" & strName & "," & strValue, ex.Message)
                Finally
                    dbCmd = Nothing
                End Try

            End If

            Return
        End Sub


        '=====================================================================
        '函 数 名: User_WritePublicValue
        '参    数: strName = 变量名
        '          strValue = 默认值
        '          strReason = 修改原因
        '返 回 值: 
        '功能描述: 保存[用户设定.mdb]的[全局设定]
        '=====================================================================
        Public Sub User_WritePublicValue(strName As String, strValue As String, strReason As String)
            If strName = "" Then
                log.WriteLogAssert("写用户通用设定", "strName=空")
                Return
            End If

            If User_ReadPublicValue(strName, "未发现变量") = "未发现变量" Then
                User_AddPublicValue(strName, strValue, strReason)
            Else
                User_EditPublicValue(strName, strValue, strReason)
            End If

            Return
        End Sub


        '=====================================================================
        '函 数 名: Fact_ReadPublicValue
        '参    数: strName = 变量名
        '          strDefault = 默认值
        '返 回 值: 变量值
        '功能描述: 读取[出厂设定.mdb]的[全局设定]，读出指定变量值
        '=====================================================================
        Public Function Fact_ReadPublicValue(strName As String, strDefault As String) As String
            If strName = "" Then
                log.WriteLogAssert("读出厂通用设定", "strName=空")
                Return ""
            End If

            Dim strResult As String = strDefault

            If Not IsNothing(g_dbConn出厂设定) Then
                Dim strCmd As String = "SELECT * FROM 全局设定 WHERE 名称 = '" & strName & "'"

                Dim dbAdapter As New OleDbDataAdapter
                Dim dbTable As New DataTable

                Try
                    dbAdapter = New OleDbDataAdapter(strCmd, g_dbConn出厂设定) '打开数据库

                    dbAdapter.Fill(dbTable) '提取数据

                    If dbTable.Rows.Count > 0 Then
                        If dbTable.Rows.Item(0).Item("名称") = strName Then
                            strResult = dbTable.Rows.Item(0).Item("值")
                        End If
                    End If
                Catch ex As Exception
                    log.WriteLogDebug("读出厂通用设定:" & strName, ex.Message)
                Finally
                    dbAdapter.Dispose()
                    dbTable = Nothing
                    dbAdapter = Nothing
                End Try

                If strResult = "空" Then
                    strResult = ""
                End If

            End If

            Return strResult
        End Function


        '=====================================================================
        '函 数 名: Fact_AddPublicValue
        '参    数: strName = 变量名
        '          strValue = 默认值
        '返 回 值: 
        '功能描述: 添加[出厂设定.mdb]的[全局设定]
        '=====================================================================
        Private Sub Fact_AddPublicValue(strName As String, strValue As String)
            If strName = "" Then
                log.WriteLogAssert("添加出厂通用设定", "strName=空")
                Return
            End If

            If strValue = "" Then
                strValue = "空"
            End If

            If Not IsNothing(g_dbConn出厂设定) Then
                Dim strInfo As String = "{" & strName & "=" & strValue & "}"
                log.WriteLogInfo("添加出厂通用设定", strInfo)

                Dim strCmd As String = "INSERT INTO 全局设定 ( [名称], [值] ) "
                strCmd &= "VALUES ( '" & strName & "', '" & strValue & "' )"

                Dim dbCmd As New OleDbCommand(strCmd, g_dbConn出厂设定)

                Try
                    dbCmd.ExecuteNonQuery()
                Catch ex As Exception
                    log.WriteLogDebug("添加出厂通用设定:" & strName & "," & strValue, ex.Message)
                Finally
                    dbCmd = Nothing
                End Try

            End If

            Return
        End Sub


        '=====================================================================
        '函 数 名: Fact_EditPublicValue
        '参    数: strName = 变量名
        '          strValue = 默认值
        '返 回 值: 
        '功能描述: 更新[出厂设定.mdb]的[全局设定]
        '=====================================================================
        Private Sub Fact_EditPublicValue(strName As String, strValue As String)
            If strName = "" Then
                log.WriteLogAssert("修改出厂通用设定", "strName=空")
                Return
            End If

            If strValue = "" Then
                strValue = "空"
            End If

            Dim strValue_pre As String = Fact_ReadPublicValue(strName, "未发现变量")

            If strValue_pre = "未发现变量" Then
                Return '未发现变量
            End If

            If strValue_pre = strValue Then
                Return '未修改，不更新
            End If

            If Not IsNothing(g_dbConn出厂设定) Then
                Dim strInfo_pre As String = "{" & strName & "=" & strValue_pre & "}"
                Dim strInfo As String = "{" & strName & "=" & strValue & "}"
                log.WriteLogInfo("修改出厂通用设定", strInfo_pre & " 变为 " & strInfo)

                Dim strCmd As String = "UPDATE 全局设定 SET 值 = '" & strValue & "' "
                strCmd &= "WHERE 名称 = '" & strName & "'"

                Dim dbCmd As New OleDbCommand(strCmd, g_dbConn出厂设定)

                Try
                    dbCmd.ExecuteNonQuery()
                Catch ex As Exception
                    log.WriteLogError("修改出厂通用设定:" & strName & "," & strValue, ex.Message)
                Finally
                    dbCmd = Nothing
                End Try

            End If

            Return
        End Sub


        '=====================================================================
        '函 数 名: Fact_WritePublicValue
        '参    数: strName = 变量名
        '          strValue = 默认值
        '返 回 值: 
        '功能描述: 保存[出厂设定.mdb]的[全局设定]
        '=====================================================================
        Public Sub Fact_WritePublicValue(strName As String, strValue As String)
            If strName = "" Then
                log.WriteLogAssert("写出厂通用设定", "strName=空")
                Return
            End If

            If Fact_ReadPublicValue(strName, "未发现变量") = "未发现变量" Then
                Fact_AddPublicValue(strName, strValue)
            Else
                Fact_EditPublicValue(strName, strValue)
            End If

            Return
        End Sub


        '=====================================================================
        '函 数 名: User_AddReport
        '参    数: udtReport = 测试报告
        '返 回 值: 
        '功能描述: 添加测试报告
        '=====================================================================
        Public Sub User_AddReport(udtReport As ReportModel)
            If udtReport.ProductId = "" Then
                log.WriteLogAssert("新建报告", "产品号=空")
                Return
            End If

            If udtReport.ProductCode = "" Then
                log.WriteLogAssert("新建报告", "产品编码=空")
                Return
            End If

            If udtReport.ReportId = "" Then
                log.WriteLogAssert("新建报告", "报告号=空")
                Return
            End If

            If Not IsNothing(g_dbConn测试记录) Then
                Dim strCmd As String = "INSERT INTO 报告管理 ( "
                strCmd &= "[报告号],"
                strCmd &= "[产品号],"
                strCmd &= "[产品编码]"
                strCmd &= " )"
                strCmd &= " VALUES ( "
                strCmd &= "'" & udtReport.ReportId & "',"
                strCmd &= "'" & udtReport.ProductId & "',"
                strCmd &= "'" & udtReport.ProductCode & "'"
                strCmd &= " )"

                Dim strInfo As String = "{"
                strInfo &= "报告号=" & udtReport.ReportId & ","
                strInfo &= "产品号=" & udtReport.ProductId & ","
                strInfo &= "产品编码=" & udtReport.ProductCode & ""
                strInfo &= "}"
                log.WriteLogInfo("新建报告", strInfo)

                Dim dbCmd As New OleDbCommand(strCmd, g_dbConn测试记录)

                Try
                    dbCmd.ExecuteNonQuery()
                Catch ex As Exception
                    log.WriteLogError("新建报告:" & strInfo, ex.Message)
                Finally
                    dbCmd = Nothing
                End Try

            End If

            Return
        End Sub


        '=====================================================================
        '函 数 名: User_ListProduct
        '参    数: 
        '返 回 值: 产品号列表
        '功能描述: 读取产品号列表
        '=====================================================================
        Public Function User_ListProduct() As List(Of String)
            Dim alstProduct As New List(Of String)

            If Not IsNothing(g_dbConn测试记录) Then
                Dim strCmd As String = "SELECT * FROM 产品管理 WHERE 临时存储=False ORDER BY 产品号"

                Dim dbAdapter As New OleDbDataAdapter
                Dim dbTable As New DataTable

                Try
                    dbAdapter = New OleDbDataAdapter(strCmd, g_dbConn测试记录) '打开数据库

                    dbAdapter.Fill(dbTable) '提取数据

                    If dbTable.Rows.Count > 0 Then
                        Dim i As UInt16

                        For i = 0 To dbTable.Rows.Count - 1
                            alstProduct.Add(dbTable.Rows.Item(i).Item("产品号"))
                        Next
                    End If
                Catch ex As Exception
                    log.WriteLogDebug("读取产品号列表", ex.Message)
                Finally
                    dbAdapter.Dispose()
                    dbTable = Nothing
                    dbAdapter = Nothing
                End Try

            End If

            Return alstProduct
        End Function


        '=====================================================================
        '函 数 名: User_ListProductAndName
        '参    数: 
        '返 回 值: 产品号列表
        '功能描述: 读取产品号列表和名称
        '=====================================================================
        Public Function User_ListProductAndName() As List(Of String)
            Dim alstProduct As New List(Of String)

            If Not IsNothing(g_dbConn测试记录) Then
                Dim strCmd As String = "SELECT * FROM 产品管理 WHERE 临时存储=False ORDER BY 产品号"

                Dim dbAdapter As New OleDbDataAdapter
                Dim dbTable As New DataTable

                Try
                    dbAdapter = New OleDbDataAdapter(strCmd, g_dbConn测试记录) '打开数据库

                    dbAdapter.Fill(dbTable) '提取数据

                    If dbTable.Rows.Count > 0 Then
                        Dim i As UInt16

                        For i = 0 To dbTable.Rows.Count - 1
                            alstProduct.Add(dbTable.Rows.Item(i).Item("产品号") & "  /  " & dbTable.Rows.Item(i).Item("产品名称"))
                        Next
                    End If
                Catch ex As Exception
                    log.WriteLogDebug("读取产品号列表和名称", ex.Message)
                Finally
                    dbAdapter.Dispose()
                    dbTable = Nothing
                    dbAdapter = Nothing
                End Try

            End If

            Return alstProduct
        End Function


        '=====================================================================
        '函 数 名: User_ReadProduct
        '参    数: strID = 产品号
        '返 回 值: 产品设定
        '功能描述: 读取产品设定
        '=====================================================================
        Public Function User_ReadProduct(strID As String) As ProductModel
            Dim udtProduct As New ProductModel
            udtProduct.Id = ""

            If strID = "" Then
                log.WriteLogAssert("读取产品", "产品号=空")
                Return udtProduct
            End If

            If Not IsNothing(g_dbConn测试记录) Then
                Dim strCmd As String = "SELECT * FROM 产品管理 WHERE 产品号 = '" & strID & "'"

                Dim dbAdapter As New OleDbDataAdapter
                Dim dbTable As New DataTable

                Try
                    dbAdapter = New OleDbDataAdapter(strCmd, g_dbConn测试记录) '打开数据库

                    dbAdapter.Fill(dbTable) '提取数据

                    If dbTable.Rows.Count > 0 Then
                        If dbTable.Rows.Item(0).Item("产品号") = strID Then
                            udtProduct.Id = dbTable.Rows.Item(0).Item("产品号")
                            udtProduct.Name = dbTable.Rows.Item(0).Item("产品名称")
                            udtProduct.Model = dbTable.Rows.Item(0).Item("产品型号")
                            udtProduct.GroupId = dbTable.Rows.Item(0).Item("组号")

                            For i = 0 To udtProduct.Times.Count - 1
                                udtProduct.Times(i) = dbTable.Rows.Item(0).Item(4 + i)
                            Next

                            For i = 0 To udtProduct.Limits.Count - 1
                                udtProduct.Limits(i) = dbTable.Rows.Item(0).Item(15 + i)
                            Next

                            udtProduct.GpUnitIndex = dbTable.Rows.Item(0).Item("压力单位")
                            udtProduct.LeakUnitIndex = dbTable.Rows.Item(0).Item("泄漏量单位")


                            udtProduct.SOffsetEn = dbTable.Rows.Item(0).Item("小漏偏差校准模式")
                            udtProduct.SOffsetVal = dbTable.Rows.Item(0).Item("小漏偏差值")
                            udtProduct.SLinearEn = dbTable.Rows.Item(0).Item("小漏线性校准模式")
                            udtProduct.SLinearK = dbTable.Rows.Item(0).Item("小漏线性系数K")
                            udtProduct.SLinearB = dbTable.Rows.Item(0).Item("小漏线性系数B")
                            udtProduct.LOffsetEn = dbTable.Rows.Item(0).Item("大漏偏差校准模式")
                            udtProduct.LOffsetVal = dbTable.Rows.Item(0).Item("大漏偏差值")
                            udtProduct.LLinearEn = dbTable.Rows.Item(0).Item("大漏线性校准模式")
                            udtProduct.LLinearK = dbTable.Rows.Item(0).Item("大漏线性系数K")
                            udtProduct.LLinearB = dbTable.Rows.Item(0).Item("大漏线性系数B")

                            udtProduct.FittingMode = dbTable.Rows.Item(0).Item("Fitting模式")
                            udtProduct.FittingA = dbTable.Rows.Item(0).Item("Fitting系数A")
                            udtProduct.FittingB = dbTable.Rows.Item(0).Item("Fitting系数B")
                            udtProduct.FittingC = dbTable.Rows.Item(0).Item("Fitting系数C")

                            udtProduct.RevEn = dbTable.Rows.Item(0).Item("加权平均补偿")
                            udtProduct.RevSave = dbTable.Rows.Item(0).Item("补偿值保存")
                            udtProduct.RevUl = dbTable.Rows.Item(0).Item("补偿值上限")
                            udtProduct.RevVal = dbTable.Rows.Item(0).Item("当前补偿值")
                            udtProduct.RevWeight = dbTable.Rows.Item(0).Item("补偿系数")
                            udtProduct.RevNg = dbTable.Rows.Item(0).Item("补偿有效结果上限")

                            udtProduct.WorkVal = dbTable.Rows.Item(0).Item("被测物容积(mL)")
                            udtProduct.MasterVal = dbTable.Rows.Item(0).Item("基准物容积(mL)")
                            udtProduct.RevCalc = dbTable.Rows.Item(0).Item("负向泄漏计算")
                            udtProduct.StandLeak = dbTable.Rows.Item(0).Item("标准漏孔值(mL/min)")
                        End If
                    End If
                Catch ex As Exception
                    log.WriteLogDebug("读取产品:" & strID, ex.Message)
                Finally
                    dbAdapter.Dispose()
                    dbTable = Nothing
                    dbAdapter = Nothing
                End Try

            End If

            Return udtProduct
        End Function


        '=====================================================================
        '函 数 名: User_AddProduct
        '参    数: udtProduct = 产品设定
        '          strReason = 修改原因
        '返 回 值: 
        '功能描述: 添加产品设定
        '=====================================================================
        Private Function User_AddProduct(udtProduct As ProductModel, strReason As String)
            If udtProduct.Id = "" Then
                log.WriteLogAssert("添加产品", "产品号=空")
                Return False
            End If

            If Not IsNothing(g_dbConn测试记录) Then
                Dim strCmd As String = "INSERT INTO 产品管理 ( "
                strCmd &= "[产品号],"
                strCmd &= "[产品名称],"
                strCmd &= "[产品型号],"

                strCmd &= "[组号],"
                strCmd &= "[时间_延时夹紧],"
                strCmd &= "[时间_充气1],"
                strCmd &= "[时间_充气2],"
                strCmd &= "[时间_平衡1],"
                strCmd &= "[时间_平衡2],"
                strCmd &= "[时间_小漏],"
                strCmd &= "[时间_大漏],"
                strCmd &= "[时间_延时排气],"
                strCmd &= "[时间_排气],"
                strCmd &= "[时间_延时松开],"
                strCmd &= "[时间_Fitting基准],"

                strCmd &= "[充气1上限],"
                strCmd &= "[充气1下限],"
                strCmd &= "[充气2上限],"
                strCmd &= "[充气2下限],"
                strCmd &= "[BNG上限],"
                strCmd &= "[BNG下限],"
                strCmd &= "[SNG上限],"
                strCmd &= "[SNG下限],"
                strCmd &= "[LNG上限],"
                strCmd &= "[LNG下限],"
                strCmd &= "[FNG上限],"
                strCmd &= "[FNG下限],"

                strCmd &= "[压力单位],"
                strCmd &= "[泄漏量单位],"


                strCmd &= "[小漏偏差校准模式],"
                strCmd &= "[小漏偏差值],"
                strCmd &= "[小漏线性校准模式],"
                strCmd &= "[小漏线性系数K],"
                strCmd &= "[小漏线性系数B],"
                strCmd &= "[大漏偏差校准模式],"
                strCmd &= "[大漏偏差值],"
                strCmd &= "[大漏线性校准模式],"
                strCmd &= "[大漏线性系数K],"
                strCmd &= "[大漏线性系数B],"


                strCmd &= "[Fitting模式],"
                strCmd &= "[Fitting系数A],"
                strCmd &= "[Fitting系数B],"
                strCmd &= "[Fitting系数C],"


                strCmd &= "[加权平均补偿],"
                strCmd &= "[补偿值保存],"
                strCmd &= "[补偿值上限],"
                strCmd &= "[当前补偿值],"
                strCmd &= "[补偿系数],"
                strCmd &= "[补偿有效结果上限],"

                strCmd &= "[被测物容积(mL)],"
                strCmd &= "[基准物容积(mL)],"
                strCmd &= "[负向泄漏计算],"
                strCmd &= "[标准漏孔值(mL/min)]"
                strCmd &= " )"
                strCmd &= " VALUES ( "
                strCmd &= "'" & udtProduct.Id & "'," '文本
                strCmd &= "'" & udtProduct.Name & "'," '文本
                strCmd &= "'" & udtProduct.Model & "'," '文本
                strCmd &= udtProduct.GroupId & ","

                For i = 0 To udtProduct.Times.Count - 1
                    strCmd &= "" & udtProduct.Times(i) & ","
                Next


                For i = 0 To udtProduct.Limits.Count - 1
                    strCmd &= "" & udtProduct.Limits(i) & ","
                Next

                strCmd &= "" & udtProduct.GpUnitIndex & ","
                strCmd &= "" & udtProduct.LeakUnitIndex & ","


                strCmd &= "" & udtProduct.SOffsetEn & ","
                strCmd &= "" & udtProduct.SOffsetVal & ","
                strCmd &= "" & udtProduct.SLinearEn & ","
                strCmd &= "" & udtProduct.SLinearK & ","
                strCmd &= "" & udtProduct.SLinearB & ","
                strCmd &= "" & udtProduct.LOffsetEn & ","
                strCmd &= "" & udtProduct.LOffsetVal & ","
                strCmd &= "" & udtProduct.LLinearEn & ","
                strCmd &= "" & udtProduct.LLinearK & ","
                strCmd &= "" & udtProduct.LLinearB & ","

                strCmd &= "" & udtProduct.FittingMode & ","
                strCmd &= "" & udtProduct.FittingA & ","
                strCmd &= "" & udtProduct.FittingB & ","
                strCmd &= "" & udtProduct.FittingC & ","

                strCmd &= "" & udtProduct.RevEn & ","
                strCmd &= "" & udtProduct.RevSave & ","
                strCmd &= "" & udtProduct.RevUl & ","
                strCmd &= "" & udtProduct.RevVal & ","
                strCmd &= "" & udtProduct.RevWeight & ","
                strCmd &= "" & udtProduct.RevNg & ","

                strCmd &= "" & udtProduct.WorkVal & ","
                strCmd &= "" & udtProduct.MasterVal & ","
                strCmd &= "" & udtProduct.RevVal & ","
                strCmd &= "" & udtProduct.StandLeak & ""
                strCmd &= " )"

                Dim strInfo As String = "{"
                strInfo &= "产品号=" & udtProduct.Id & ","
                strInfo &= "产品名称=" & udtProduct.Name & ","
                strInfo &= "产品型号=" & udtProduct.Model & ","
                strInfo &= "组号=" & udtProduct.GroupId & ","

                For i = 0 To udtProduct.Times.Count - 1
                    strInfo &= g_strResultTitle(24 + i) & "=" & udtProduct.Times(i) & ","
                Next

                For i = 0 To udtProduct.Limits.Count - 1
                    strInfo &= g_strResultTitle(35 + i) & "=" & udtProduct.Limits(i) & ","
                Next

                strInfo &= "压力单位=" & g_strGPUnit(udtProduct.GpUnitIndex) & ","
                If udtProduct.LeakUnitIndex = 1 Then
                    strInfo &= "泄漏量单位=" & g_strGPUnit(udtProduct.GpUnitIndex) & ","
                Else
                    strInfo &= "泄漏量单位=" & g_strLeakUnit(udtProduct.LeakUnitIndex) & ","
                End If

                strInfo &= "小漏偏差校准模式=" & udtProduct.SOffsetEn & ","
                strInfo &= "小漏偏差值=" & udtProduct.SOffsetVal & ","
                strInfo &= "小漏线性校准模式=" & udtProduct.SLinearEn & ","
                strInfo &= "小漏线性系数K=" & udtProduct.SLinearK & ","
                strInfo &= "小漏线性系数B=" & udtProduct.SLinearB & ","
                strInfo &= "大漏偏差校准模式=" & udtProduct.LOffsetEn & ","
                strInfo &= "大漏偏差值=" & udtProduct.LOffsetVal & ","
                strInfo &= "大漏线性校准模式=" & udtProduct.LLinearEn & ","
                strInfo &= "大漏线性系数K=" & udtProduct.LLinearK & ","
                strInfo &= "大漏线性系数B=" & udtProduct.LLinearB & ","


                strInfo &= "Fitting模式=" & udtProduct.FittingMode & ","
                strInfo &= "Fitting系数A=" & udtProduct.FittingA & ","
                strInfo &= "Fitting系数B=" & udtProduct.FittingB & ","
                strInfo &= "Fitting系数C=" & udtProduct.FittingC & ","


                strInfo &= "加权平均补偿=" & udtProduct.RevEn & ","
                strInfo &= "补偿值保存=" & udtProduct.RevSave & ","
                strInfo &= "补偿值上限=" & udtProduct.RevUl & ","
                strInfo &= "当前补偿值=" & udtProduct.RevVal & ","
                strInfo &= "补偿系数=" & udtProduct.RevWeight & ","
                strInfo &= "补偿有效结果上限=" & udtProduct.RevNg & ","

                strInfo &= "被测物容积(mL)=" & udtProduct.WorkVal & ","
                strInfo &= "基准物容积(mL)=" & udtProduct.MasterVal & ","
                strInfo &= "负向泄漏计算=" & udtProduct.RevCalc & ","
                strInfo &= "标准漏孔值(mL/min)= " & udtProduct.StandLeak
                strInfo &= "}"
                log.WriteLogInfo("添加产品", "{" & "添加原因=" & strReason & ", " & strInfo & "}")

                Dim dbCmd As New OleDbCommand(strCmd, g_dbConn测试记录)

                Try
                    dbCmd.ExecuteNonQuery()
                Catch ex As Exception
                    log.WriteLogError("添加产品:" & strInfo, ex.Message)
                    Return False
                End Try
            End If
            Return True
        End Function


        '=====================================================================
        '函 数 名: User_EditProduct
        '参    数: udtProduct = 产品设定
        '          strReason = 修改原因
        '返 回 值: 
        '功能描述: 编辑产品设定
        '=====================================================================
        Private Function User_EditProduct(udtProduct As ProductModel, strReason As String) As Boolean
            If udtProduct.Id = "" Then
                log.WriteLogAssert("编辑产品", "产品号=空")
                Return False
            End If

            Dim shouldWrite = g_udtProduct.Id = udtProduct.Id
            Dim shouldNotify = False

            If Not IsNothing(g_dbConn测试记录) Then
                Dim udtProduct_pre As ProductModel = User_ReadProduct(udtProduct.Id)

                Dim strCmd As String = ""
                Dim strInfo As String = "{" & "修改原因=" & strReason & ",产品号=" & udtProduct.Id & ","

                If udtProduct_pre.Name <> udtProduct.Name Then
                    strCmd &= "产品名称='" & udtProduct.Name & "'," '文本
                    strInfo &= "{产品名称=" & udtProduct_pre.Name & "}变为{产品名称=" & udtProduct.Name & "},"
                End If

                If udtProduct_pre.Model <> udtProduct.Model Then
                    strCmd &= "产品型号='" & udtProduct.Model & "'," '文本
                    strInfo &= "{产品型号=" & udtProduct_pre.Model & "}变为{产品型号=" & udtProduct.Model & "},"
                End If

                Dim TOLERANCE As Single = 0.000001
                For i = 0 To udtProduct_pre.Times.Count - 1
                    If Math.Abs(udtProduct_pre.Times(i) - udtProduct.Times(i)) > TOLERANCE Then
                        strCmd &= g_strResultTitle(24 + i) & "=" & udtProduct.Times(i) & ","
                        strInfo &= "{" & g_strResultTitle(24 + i) & "=" & udtProduct_pre.Times(i) & "}变为{" &
                                   g_strResultTitle(24 + i) & "=" & udtProduct.Times(i) & "},"
                        If shouldWrite Then
                            uLPU.OUT_WriteSingle(1, ADDR_OUT_TIME_DELAY1 + i * 2, udtProduct.Times(i))
                            shouldNotify = True
                        End If
                    End If
                Next

                For i = 0 To udtProduct_pre.Limits.Count - 1
                    If Math.Abs(udtProduct_pre.Limits(i) - udtProduct.Limits(i)) > TOLERANCE Then
                        strCmd &= g_strResultTitle(35 + i) & "=" & udtProduct.Limits(i) & ","
                        strInfo &= "{" & g_strResultTitle(35 + i) & "=" & udtProduct_pre.Limits(i) & "}变为{" &
                                   g_strResultTitle(35 + i) & "=" & udtProduct.Limits(i) & "},"
                        If shouldWrite Then
                            uLPU.OUT_WriteSingle(1, ADDR_OUT_LEAD_P_UP + i * 2, udtProduct.Limits(i))
                            shouldNotify = True
                        End If
                    End If
                Next


                If udtProduct_pre.GpUnitIndex <> udtProduct.GpUnitIndex Then
                    strCmd &= "压力单位=" & udtProduct.GpUnitIndex & ","
                    strInfo &= "{压力单位=" & g_strGPUnit(udtProduct_pre.GpUnitIndex) & "}变为{压力单位=" &
                               g_strGPUnit(udtProduct.GpUnitIndex) & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteUint16(1, ADDR_OUT_GP_UNIT, udtProduct.GpUnitIndex)
                        shouldNotify = True
                    End If
                End If


                If udtProduct_pre.LeakUnitIndex <> udtProduct.LeakUnitIndex Then
                    strCmd &= "泄漏量单位=" & udtProduct.LeakUnitIndex & ","
                    Dim leakUnitPre As String
                    Dim leakUnit As String

                    If udtProduct.LeakUnitIndex = 1 Then
                        leakUnit = g_strGPUnit(udtProduct.GpUnitIndex)
                    Else
                        leakUnit = g_strLeakUnit(udtProduct.LeakUnitIndex)
                    End If

                    If udtProduct_pre.LeakUnitIndex = 1 Then
                        leakUnitPre = g_strGPUnit(udtProduct_pre.GpUnitIndex)
                    Else
                        leakUnitPre = g_strLeakUnit(udtProduct_pre.LeakUnitIndex)
                    End If

                    strInfo &= "{泄漏量单位=" & leakUnitPre & "}变为{泄漏量单位=" & leakUnit & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteUint16(1, ADDR_OUT_SDET_UNIT, udtProduct.GpUnitIndex)
                        shouldNotify = True
                    End If
                End If

                If udtProduct_pre.SOffsetEn <> udtProduct.SOffsetEn Then
                    strCmd &= "小漏偏差校准模式=" & udtProduct.SOffsetEn & ","
                    strInfo &= "{小漏偏差校准模式=" & udtProduct_pre.SOffsetEn & "}变为{小漏偏差校准模式=" & udtProduct.SOffsetEn & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteUint16(1, ADDR_OUT_SDET_OFFICE_EN, IIf(udtProduct.SOffsetEn, 1, 0))
                        shouldNotify = True
                    End If
                End If

                If Math.Abs(udtProduct_pre.SOffsetVal - udtProduct.SOffsetVal) > TOLERANCE Then
                    strCmd &= "小漏偏差值=" & udtProduct.SOffsetVal & ","
                    strInfo &= "{小漏偏差值=" & udtProduct_pre.SOffsetVal & "}变为{小漏偏差值=" & udtProduct.SOffsetVal & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteSingle(1, ADDR_OUT_SDET_OFFICE_VALUE, udtProduct.SOffsetVal)
                        shouldNotify = True
                    End If
                End If

                If udtProduct_pre.SLinearEn <> udtProduct.SLinearEn Then
                    strCmd &= "小漏线性校准模式=" & udtProduct.SLinearEn & ","
                    strInfo &= "{小漏线性校准模式=" & udtProduct_pre.SLinearEn & "}变为{小漏线性校准模式=" & udtProduct.SLinearEn & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteUint16(1, ADDR_OUT_SDET_LINEAR_EN, IIf(udtProduct.SLinearEn, 1, 0))
                        shouldNotify = True
                    End If
                End If

                If Math.Abs(udtProduct_pre.SLinearK - udtProduct.SLinearK) > TOLERANCE Then
                    strCmd &= "小漏线性系数K=" & udtProduct.SLinearK & ","
                    strInfo &= "{小漏线性系数K=" & udtProduct_pre.SLinearK & "}变为{小漏线性系数K=" & udtProduct.SLinearK & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteSingle(1, ADDR_OUT_SDET_LINEAR_K, udtProduct.SLinearK)
                        shouldNotify = True
                    End If
                End If

                If Math.Abs(udtProduct_pre.SLinearB - udtProduct.SLinearB) > TOLERANCE Then
                    strCmd &= "小漏线性系数B=" & udtProduct.SLinearB & ","
                    strInfo &= "{小漏线性系数B=" & udtProduct_pre.SLinearB & "}变为{小漏线性系数B=" & udtProduct.SLinearB & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteSingle(1, ADDR_OUT_SDET_LINEAR_B, udtProduct.SLinearB)
                        shouldNotify = True
                    End If
                End If


                If udtProduct_pre.LOffsetEn <> udtProduct.LOffsetEn Then
                    strCmd &= "大漏偏差校准模式=" & udtProduct.LOffsetEn & ","
                    strInfo &= "{大漏偏差校准模式=" & udtProduct_pre.LOffsetEn & "}变为{大漏偏差校准模式=" & udtProduct.LOffsetEn & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteUint16(1, ADDR_OUT_LDET_OFFICE_EN, IIf(udtProduct.LOffsetEn, 1, 0))
                        shouldNotify = True
                    End If
                End If

                If Math.Abs(udtProduct_pre.LOffsetVal - udtProduct.LOffsetVal) > TOLERANCE Then
                    strCmd &= "大漏偏差值=" & udtProduct.LOffsetVal & ","
                    strInfo &= "{大漏偏差值=" & udtProduct_pre.LOffsetVal & "}变为{大漏偏差值=" & udtProduct.LOffsetVal & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteSingle(1, ADDR_OUT_LDET_OFFICE_VALUE, udtProduct.LOffsetVal)
                        shouldNotify = True
                    End If
                End If

                If udtProduct_pre.LLinearEn <> udtProduct.LLinearEn Then
                    strCmd &= "大漏线性校准模式=" & udtProduct.LLinearEn & ","
                    strInfo &= "{大漏线性校准模式=" & udtProduct_pre.LLinearEn & "}变为{大漏线性校准模式=" & udtProduct.LLinearEn & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteUint16(1, ADDR_OUT_LDET_LINEAR_EN, IIf(udtProduct.LLinearEn, 1, 0))
                        shouldNotify = True
                    End If
                End If

                If Math.Abs(udtProduct_pre.LLinearK - udtProduct.LLinearK) > TOLERANCE Then
                    strCmd &= "大漏线性系数K=" & udtProduct.LLinearK & ","
                    strInfo &= "{大漏线性系数K=" & udtProduct_pre.LLinearK & "}变为{大漏线性系数K=" & udtProduct.LLinearK & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteSingle(1, ADDR_OUT_LDET_LINEAR_K, udtProduct.LLinearK)
                        shouldNotify = True
                    End If
                End If

                If Math.Abs(udtProduct_pre.LLinearB - udtProduct.LLinearB) > TOLERANCE Then
                    strCmd &= "大漏线性系数B=" & udtProduct.LLinearB & ","
                    strInfo &= "{大漏线性系数B=" & udtProduct_pre.LLinearB & "}变为{大漏线性系数B=" & udtProduct.LLinearB & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteSingle(1, ADDR_OUT_LDET_LINEAR_B, udtProduct.LLinearB)
                        shouldNotify = True
                    End If
                End If


                If udtProduct_pre.FittingMode <> udtProduct.FittingMode Then
                    strCmd &= "Fitting模式=" & udtProduct.FittingMode & ","
                    strInfo &= "{Fitting模式=" & udtProduct_pre.FittingMode & "}变为{Fitting模式=" & udtProduct.FittingMode & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteUint16(1, ADDR_OUT_FITTING_EN, udtProduct.FittingMode)
                        shouldNotify = True
                    End If
                End If

                If Math.Abs(udtProduct_pre.FittingA - udtProduct.FittingA) > TOLERANCE Then
                    strCmd &= "Fitting系数A=" & udtProduct.FittingA & ","
                    strInfo &= "{Fitting系数A=" & udtProduct_pre.FittingA & "}变为{Fitting系数A=" & udtProduct.FittingA & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteSingle(1, ADDR_OUT_FITTING_A, udtProduct.FittingA)
                        shouldNotify = True
                    End If
                End If

                If Math.Abs(udtProduct_pre.FittingB - udtProduct.FittingB) > TOLERANCE Then
                    strCmd &= "Fitting系数B=" & udtProduct.FittingB & ","
                    strInfo &= "{Fitting系数B=" & udtProduct_pre.FittingB & "}变为{Fitting系数B=" & udtProduct.FittingB & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteSingle(1, ADDR_OUT_FITTING_B, udtProduct.FittingB)
                        shouldNotify = True
                    End If
                End If

                If Math.Abs(udtProduct_pre.FittingC - udtProduct.FittingC) > TOLERANCE Then
                    strCmd &= "Fitting系数C=" & udtProduct.FittingC & ","
                    strInfo &= "{Fitting系数C=" & udtProduct_pre.FittingC & "}变为{Fitting系数C=" & udtProduct.FittingC & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteSingle(1, ADDR_OUT_FITTING_C, udtProduct.FittingC)
                        shouldNotify = True
                    End If
                End If


                If udtProduct_pre.RevEn <> udtProduct.RevEn Then
                    strCmd &= "加权平均补偿=" & udtProduct.RevEn & ","
                    strInfo &= "{加权平均补偿=" & udtProduct_pre.RevEn & "}变为{加权平均补偿=" & udtProduct.RevEn & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteUint16(1, ADDR_OUT_REV_MODE, IIf(udtProduct.RevEn, 1, 0))
                        shouldNotify = True
                    End If
                End If

                If udtProduct_pre.RevSave <> udtProduct.RevSave Then
                    strCmd &= "补偿值保存=" & udtProduct.RevSave & ","
                    strInfo &= "{补偿值保存=" & udtProduct_pre.RevSave & "}变为{补偿值保存=" & udtProduct.RevSave & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteUint16(1, ADDR_OUT_REV_SAVE, IIf(udtProduct.RevSave, 1, 0))
                        shouldNotify = True
                    End If
                End If

                If Math.Abs(udtProduct_pre.RevUl - udtProduct.RevUl) > TOLERANCE Then
                    strCmd &= "补偿值上限=" & udtProduct.RevUl & ","
                    strInfo &= "{补偿值上限=" & udtProduct_pre.RevUl & "}变为{补偿值上限=" & udtProduct.RevUl & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteSingle(1, ADDR_OUT_REV_LIMIT, udtProduct.RevUl)
                        shouldNotify = True
                    End If
                End If

                If Math.Abs(udtProduct_pre.RevVal - udtProduct.RevVal) > TOLERANCE Then
                    strCmd &= "当前补偿值=" & udtProduct.RevVal & ","
                    strInfo &= "{当前补偿值=" & udtProduct_pre.RevVal & "}变为{当前补偿值=" & udtProduct.RevVal & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteSingle(1, ADDR_OUT_REV_DATA, udtProduct.RevVal)
                        shouldNotify = True
                    End If
                End If

                If Math.Abs(udtProduct_pre.RevWeight - udtProduct.RevWeight) > TOLERANCE Then
                    strCmd &= "补偿系数=" & udtProduct.RevWeight & ","
                    strInfo &= "{补偿系数=" & udtProduct_pre.RevWeight & "}变为{补偿系数=" & udtProduct.RevWeight & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteSingle(1, ADDR_OUT_REV_WEIGHT, udtProduct.RevWeight)
                        shouldNotify = True
                    End If
                End If

                If Math.Abs(udtProduct_pre.RevNg - udtProduct.RevNg) > TOLERANCE Then
                    strCmd &= "补偿有效结果上限=" & udtProduct.RevNg & ","
                    strInfo &= "{补偿有效结果上限=" & udtProduct_pre.RevNg & "}变为{补偿有效结果上限=" & udtProduct.RevNg & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteSingle(1, ADDR_OUT_REV_NG, udtProduct.RevNg)
                        shouldNotify = True
                    End If
                End If

                If Math.Abs(udtProduct_pre.WorkVal - udtProduct.WorkVal) > TOLERANCE Then
                    strCmd &= "[被测物容积(mL)]=" & udtProduct.WorkVal & ","
                    strInfo &= "{被测物容积(mL)=" & udtProduct_pre.WorkVal & "}变为{被测物容积(mL)=" & udtProduct.WorkVal & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteSingle(1, ADDR_OUT_WORK_VOL, udtProduct.WorkVal)
                        shouldNotify = True
                    End If
                End If

                If Math.Abs(udtProduct_pre.MasterVal - udtProduct.MasterVal) > TOLERANCE Then
                    strCmd &= "[基准物容积(mL)]=" & udtProduct.MasterVal & ","
                    strInfo &= "{基准物容积(mL)=" & udtProduct_pre.MasterVal & "}变为{基准物容积(mL)=" & udtProduct.MasterVal & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteSingle(1, ADDR_OUT_MASTER_VOL, udtProduct.MasterVal)
                        shouldNotify = True
                    End If
                End If

                If udtProduct_pre.RevCalc - udtProduct.RevCalc > TOLERANCE Then
                    strCmd &= "负向泄漏计算=" & udtProduct.RevCalc & ","
                    strInfo &= "{负向泄漏计算=" & udtProduct_pre.RevCalc & "}变为{负向泄漏计算=" & udtProduct.RevCalc & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteSingle(1, ADDR_OUT_NEGATIVE_CALCULATION, IIf(udtProduct.RevCalc, 1, 0))
                        shouldNotify = True
                    End If
                End If

                If Math.Abs(udtProduct_pre.StandLeak - udtProduct.StandLeak) > TOLERANCE Then
                    strCmd &= "[标准漏孔值(mL/min)]=" & udtProduct.StandLeak & ","
                    strInfo &= "{标准漏孔值(mL/min)=" & udtProduct_pre.StandLeak & "}变为{标准漏孔值(mL/min)=" & udtProduct.StandLeak & "},"
                    If shouldWrite Then
                        uLPU.OUT_WriteSingle(1, ADDR_OUT_LEAK_VALUE, udtProduct.StandLeak)
                        shouldNotify = True
                    End If
                End If


                If strCmd = "" Then '无修改
                    Return True
                End If

                '去掉最后的【,】
                strCmd = Mid(strCmd, 1, strCmd.Length - 1)
                strInfo = Mid(strInfo, 1, strInfo.Length - 1)

                strCmd = "UPDATE 产品管理 SET " & strCmd & " WHERE 产品号='" & udtProduct.Id & "'" '文本
                strInfo &= "}"

                log.WriteLogInfo("编辑产品", strInfo)

                Dim dbCmd As New OleDbCommand(strCmd, g_dbConn测试记录)

                Try
                    dbCmd.ExecuteNonQuery()
                    If shouldWrite And shouldNotify Then
                        Messenger.Default.Send(Of String)("OK", "update_product")
                    End If

                Catch ex As Exception
                    log.WriteLogError("编辑产品:" & strInfo, ex.Message)
                    Return False
                End Try
            Else
                Return False
            End If

            Return True
        End Function


        '=====================================================================
        '函 数 名: User_WriteProduct
        '参    数: udtProduct = 产品设定
        '          strReason = 修改原因
        '返 回 值: 
        '功能描述: 写产品设定
        '=====================================================================
        Public Function User_WriteProduct(udtProduct As ProductModel, strReason As String) As Boolean
            If udtProduct.Id = "" Then
                log.WriteLogAssert("写产品信息", "产品号=空")
                Return False
            End If

            Dim udtProduct2 As ProductModel

            udtProduct2 = User_ReadProduct(udtProduct.Id)

            If udtProduct2.Id = "" Then '没找到
                Return User_AddProduct(udtProduct, strReason)
            Else
                Return User_EditProduct(udtProduct, strReason)
            End If
        End Function


        '=====================================================================
        '函 数 名: User_AddRecord
        '参    数: lvwResult = 测试结果表格，最后行为当前结果
        '返 回 值: 
        '功能描述: 添加测试记录(1条)
        '=====================================================================
        Public Sub User_AddRecord(dataRow As DataRow)
            Dim i As UInt16
            Dim blnNeedDel As Boolean = False
            For i = 0 To g_strResultTitle.Count - 1
                If IsDBNull(dataRow.Item(i)) Then
                    blnNeedDel = True
                End If
            Next

            If blnNeedDel Then
                Exit Sub
            End If

            If Not IsNothing(g_dbConn测试记录) Then
                Dim strCmd As String = "INSERT INTO 测试记录 ( "
                For i = 0 To g_strResultTitle.Length - 1
                    strCmd &= "[" & g_strResultTitle(i) & "],"
                Next
                strCmd &= "[" & "用户名" & "]"
                strCmd &= " )"
                strCmd &= " VALUES ( "
                For i = 0 To g_strResultTitle.Length - 1
                    If (i >= 0 And i <= 5) Or i = 9 Or i = 12 Or i = 15 Or (i >= 19 And i <= 22) Then
                        strCmd &= "'" & dataRow.Item(i) & "',"
                    ElseIf i = 6 Then
                        strCmd &= "#" & dataRow.Item(i) & "#,"
                    Else
                        strCmd &= dataRow.Item(i) & ","
                    End If
                Next

                strCmd &= "'" & SystemData.g_strUserName & "'"
                strCmd &= " )"

                Dim strInfo As String = "{"

                strInfo &= "用户名=" & SystemData.g_strUserName & ","
                For i = 0 To g_strResultTitle.Length - 1
                    strInfo &= g_strResultTitle(i) & "=" & dataRow(i) & ","
                Next

                strInfo = Mid(strInfo, 1, strInfo.Length - 1)
                strInfo &= "}"
                log.WriteLogInfo("新增记录", strInfo)

                Dim dbCmd As New OleDbCommand(strCmd, g_dbConn测试记录)

                Try
                    dbCmd.ExecuteNonQuery()
                Catch ex As Exception
                    log.WriteLogError("新增记录:", "sql :" & strCmd & ",错误信息:" & ex.Message)
                Finally
                    dbCmd = Nothing
                End Try
            End If

            Return
        End Sub

        Public Sub User_AddRecord800(dataRow As DataRow, _isFullTable As Boolean)
            Dim i As UInt16
            Dim blnNeedDel As Boolean = False
            If _isFullTable Then
                For i = 0 To g_strResult_800.Count - 1
                    If IsDBNull(dataRow.Item(i)) Then
                        blnNeedDel = True
                    End If
                Next
            End If



            If blnNeedDel Then
                Exit Sub
            End If

            If Not IsNothing(g_dbConn测试记录) Then

                Dim strCmd As String
                If _isFullTable Then
                    strCmd = "INSERT INTO 测试数据记录 ( "

                    For i = 0 To g_strResult_800.Length - 1
                        strCmd &= "[" & g_strResult_800(i) & "],"
                    Next
                    strCmd &= "[" & "用户名" & "]"
                    strCmd &= " )"
                    strCmd &= " VALUES ( "
                    For i = 0 To g_strResult_800.Length - 1
                        If (i >= 0 And i <= 5) Or (i >= 8 And i <= 11) Or i = 22 Or (i >= 40 And i <= 43) Then
                            strCmd &= "'" & dataRow.Item(i) & "',"
                        ElseIf i = 6 Then
                            strCmd &= "#" & dataRow.Item(i) & "#,"
                        Else
                            strCmd &= dataRow.Item(i) & ","
                        End If
                    Next

                    strCmd &= "'" & SystemData.g_strUserName & "'"
                    strCmd &= " )"

                    Dim strInfo As String = "{"

                    strInfo &= "用户名=" & SystemData.g_strUserName & ","
                    For i = 0 To g_strResult_800.Length - 1
                        strInfo &= g_strResult_800(i) & "=" & dataRow(i) & ","
                    Next

                    strInfo = Mid(strInfo, 1, strInfo.Length - 1)
                    strInfo &= "}"
                    log.WriteLogInfo("新增记录", strInfo)
                Else
                    strCmd = "INSERT INTO 测试记录 ( "

                    For i = 0 To g_strCol_800.Length - 1
                        strCmd &= "[" & g_strCol_800(i) & "],"
                    Next

                    strCmd &= "[" & "用户名" & "]"
                    strCmd &= " )"
                    strCmd &= " VALUES ( "

                    For i = 0 To g_strCol_800.Length - 1
                        If i = 3 Or i = 12 Or i = 13 Then
                            strCmd &= "'" & dataRow.Item(i) & "',"
                        ElseIf i = 2 Then
                            strCmd &= "#" & dataRow.Item(i) & "#,"
                        Else
                            strCmd &= dataRow.Item(i) & ","
                        End If
                    Next

                    strCmd &= "'" & SystemData.g_strUserName & "'"
                    strCmd &= " )"

                End If
                Dim dbCmd As New OleDbCommand(strCmd, g_dbConn测试记录)

                Try
                    dbCmd.ExecuteNonQuery()
                Catch ex As Exception
                    log.WriteLogError("新增记录:", "sql :" & strCmd & ",错误信息:" & ex.Message)
                Finally
                    dbCmd = Nothing
                End Try
            End If

            Return
        End Sub

        Public Sub User_AddRecord800MS(dataRow As DataRow, _isFullTable As Boolean)
            Dim i As UInt16
            Dim blnNeedDel As Boolean = False
            For i = 0 To g_strResultTitle.Count - 1
                If IsDBNull(dataRow.Item(i)) Then
                    blnNeedDel = True
                End If
            Next

            If blnNeedDel Then
                Exit Sub
            End If

            If Not IsNothing(g_dbConn测试记录) Then
                Dim strCmd As String

                If _isFullTable Then

                    strCmd = "INSERT INTO 测试数据记录 ( "
                    For i = 0 To g_strResultTitle.Length - 1
                        strCmd &= "[" & g_strResultTitle(i) & "],"
                    Next
                    strCmd &= "[" & "用户名" & "]"
                    strCmd &= " )"
                    strCmd &= " VALUES ( "
                    For i = 0 To g_strResult_800MS.Length - 1
                        If (i >= 0 And i <= 5) Or i = 9 Or i = 12 Or i = 15 Or (i >= 19 And i <= 22) Then
                            strCmd &= "'" & dataRow.Item(i) & "',"
                        ElseIf i = 6 Then
                            strCmd &= "#" & dataRow.Item(i) & "#,"
                        Else
                            strCmd &= dataRow.Item(i) & ","
                        End If
                    Next

                    strCmd &= "'" & SystemData.g_strUserName & "'"
                    strCmd &= " )"

                    Dim strInfo As String = "{"

                    strInfo &= "用户名=" & SystemData.g_strUserName & ","
                    For i = 0 To g_strResultTitle.Length - 1
                        strInfo &= g_strResultTitle(i) & "=" & dataRow(i) & ","
                    Next

                    strInfo = Mid(strInfo, 1, strInfo.Length - 1)
                    strInfo &= "}"
                    log.WriteLogInfo("新增记录", strInfo)
                Else
                    strCmd = "INSERT INTO 测试记录 ( "
                    For i = 0 To g_strCol_800.Length - 1
                        strCmd &= "[" & g_strCol_800(i) & "],"
                    Next

                    strCmd &= "[" & "用户名" & "]"
                    strCmd &= " )"
                    strCmd &= " VALUES ( "

                    For i = 0 To g_strCol_800.Length - 1
                        If i = 3 Then
                            strCmd &= "'" & dataRow.Item(i) & "',"
                        ElseIf i = 2 Then
                            strCmd &= "#" & dataRow.Item(i) & "#,"
                        Else
                            strCmd &= dataRow.Item(i) & ","
                        End If
                    Next

                    strCmd &= "'" & SystemData.g_strUserName & "'"
                    strCmd &= " )"

                End If


                Dim dbCmd As New OleDbCommand(strCmd, g_dbConn测试记录)

                Try
                    dbCmd.ExecuteNonQuery()
                Catch ex As Exception
                    log.WriteLogError("新增记录:", "sql :" & strCmd & ",错误信息:" & ex.Message)
                Finally
                    dbCmd = Nothing
                End Try
            End If

            Return
        End Sub


        Public Function User_AddUser(userModel As UserModel) As Boolean
            If Not IsNothing(g_dbConn用户设定) Then
                Dim strCmd As String = "INSERT INTO 用户管理 ( "
                '[字段名],
                For i = 0 To g_strUserTitle.Count - 1
                    If i = g_strUserTitle.Count - 1 Then
                        strCmd &= "[" & g_strUserTitle(i) & "] )"
                    ElseIf i = 14 Then ' 上次登陆时间 跳过
                        Continue For
                    Else
                        strCmd &= "[" & g_strUserTitle(i) & "]" & ", "
                    End If
                Next
                strCmd &= " VALUES ( '" & userModel.Username & "', '" & userModel.Password & "', '" & userModel.Password & "', "
                For i = 0 To 9
                    strCmd &= userModel.PermissionList(i) & ","
                Next
                strCmd &= userModel.ErrorCount & ","
                strCmd &= "#" & userModel.Deadline & "# )"

                Dim strInfo As String = "{ " & "用户名=" & userModel.Username & ", " & "密码=" & "*****" & ", "
                '[字段名]=[字段值],
                For i = 3 To 12
                    strInfo &= g_strUserTitle(i) & "=" & userModel.PermissionList(i - 3)
                Next
                strInfo &= "错误次数=" & userModel.ErrorCount & ", "
                strInfo &= "密码到期日=" & userModel.Deadline
                strInfo &= " }"

                log.WriteLogInfo("添加用户", strInfo)

                Dim dbCmd As New OleDbCommand(strCmd, g_dbConn用户设定)

                Try
                    dbCmd.ExecuteNonQuery()
                Catch ex As Exception
                    log.WriteLogError("新增用户:", "sql :" & strCmd & ",错误信息:" & ex.Message)
                    Return False
                End Try
            Else
                Return False
            End If
            Return True
        End Function


        Public Function User_UpdateUser(userModel As UserModel) As Boolean
            If Not IsNothing(g_dbConn测试记录) Then
                Dim userModelPre = User_ReadUser(userModel.Username)
                Dim strCmd As String = ""
                Dim strInfoPre As String = ""
                Dim strInfo As String = ""
                If userModel.Password <> userModelPre.Password Then
                    strCmd &= "密码='" & userModel.Password & "',"
                    strInfoPre &= "密码=******,"
                    strInfo &= "密码=*****,"
                End If

                For i = 0 To 9
                    If userModel.PermissionList(i) <> userModelPre.PermissionList(i) Then
                        strCmd &= g_strUserTitle(i + 3) & "=" & userModel.PermissionList(i) & ","
                        strInfoPre &= g_strUserTitle(i + 3) & "=" & userModelPre.PermissionList(i) & ","
                        strInfo &= g_strUserTitle(i + 3) & "=" & userModel.PermissionList(i) & ","
                    End If
                Next

                If userModel.ErrorCount <> userModelPre.ErrorCount Then
                    strCmd &= "错误次数=" & userModel.ErrorCount & ","
                    strInfoPre &= "错误次数=" & userModelPre.ErrorCount & ","
                    strInfo &= "错误次数=" & userModel.ErrorCount & ","
                End If

                If userModel.Deadline <> userModelPre.Deadline Then
                    strCmd &= "密码到期日= #" & userModel.Deadline & "#,"
                    strInfoPre &= "密码到期日=" & userModelPre.Deadline & ","
                    strInfo &= "密码到期日=" & userModel.Deadline & ","
                End If

                If strCmd <> "" Then
                    strCmd = Mid(strCmd, 1, strCmd.Length - 1)
                    strInfo = Mid(strInfo, 1, strInfo.Length - 1)
                    strInfoPre = Mid(strInfoPre, 1, strInfoPre.Length - 1)


                    strCmd = "UPDATE 用户管理 SET " & strCmd & " WHERE 用户名='" & userModel.Username & "'" '文本

                    log.WriteLogInfo("编辑用户", "用户名=" & userModel.Username & ", { " & strInfoPre & " } 更新为 { " & strInfo & " }")

                    Dim dbCmd As New OleDbCommand(strCmd, g_dbConn用户设定)

                    Try
                        dbCmd.ExecuteNonQuery()
                    Catch ex As Exception
                        log.WriteLogError("编辑用户:" & strCmd, ex.Message)
                        Return False
                    End Try
                End If
            Else
                Return False
            End If

            Return True
        End Function


        Public Function User_ReadUser(username As String) As UserModel

            Dim userModel As New UserModel

            If Not IsNothing(g_dbConn用户设定) Then
                Dim strCmd As String = "SELECT * FROM 用户管理 WHERE 用户名 = '" & username & "'"

                Dim dbAdapter As New OleDbDataAdapter
                Dim dbTable As New DataTable

                Try
                    dbAdapter = New OleDbDataAdapter(strCmd, g_dbConn用户设定) '打开数据库
                    dbAdapter.Fill(dbTable) '提取数据

                    If dbTable.Rows.Count > 0 Then
                        If dbTable.Rows.Item(0).Item("用户名") = username Then
                            userModel.Username = dbTable.Rows.Item(0).Item("用户名")
                            userModel.Password = dbTable.Rows.Item(0).Item("密码")
                            For i = 0 To 9
                                userModel.PermissionList(i) = dbTable.Rows.Item(0).Item(i + 3)
                            Next
                            userModel.ErrorCount = dbTable.Rows.Item(0).Item("错误次数")
                            userModel.Deadline = dbTable.Rows.Item(0).Item("密码到期日")
                        End If
                    End If
                Catch ex As Exception
                    log.WriteLogDebug("读取用户:" & username, ex.Message)
                Finally
                    dbAdapter.Dispose()
                End Try
            End If
            Return userModel
        End Function


        Public Function User_List() As DataView

            Dim dataView As New DataView

            If Not IsNothing(g_dbConn用户设定) Then

                Dim strCmd As String = "SELECT * FROM 用户管理"

                Dim dbAdapter As New OleDbDataAdapter
                Dim dbTable As New DataTable

                Try
                    dbAdapter = New OleDbDataAdapter(strCmd, g_dbConn用户设定)
                    dbAdapter.Fill(dbTable)
                    dataView = dbTable.DefaultView
                Catch ex As Exception
                    log.WriteLogError("", ex.Message)
                Finally
                    dbAdapter.Dispose()
                End Try
            End If
            Return dataView
        End Function

        '=====================================================================
        '函 数 名: CheckUser
        '参    数: strUserName = 用户名
        '          strPassword = 密码
        '返 回 值: True = 验证OK
        '          False = 错误(用户名不存在，密码错误，密码错误次数过多，未启用，等)
        '功能描述: 读取数据库，验证用户的正确性
        '=====================================================================
        Public Function CheckUser(strUserName As String, strPassword As String) As Boolean
            If strUserName = "" Then
                log.WriteLogAssert("CheckUser()", "strUserName=空")
                Return False
            End If

            If strPassword = "" Then
                log.WriteLogAssert("CheckUser()", "strPassword=空")
                Return False
            End If

            Dim blnResult As Boolean = False

            If Not IsNothing(g_dbConn用户设定) Then
                Dim strCmd As String

                Dim dbAdapter As New OleDbDataAdapter
                Dim dbTable As New DataTable
                Dim dbCmd As New OleDbCommand

                Try
                    strCmd = "SELECT * FROM 用户管理 WHERE 用户名 = '" & strUserName & "'"
                    dbAdapter = New OleDbDataAdapter(strCmd, g_dbConn用户设定) '打开数据库

                    dbAdapter.Fill(dbTable)

                    If dbTable.Rows.Count > 1 Then
                        '用户名异常，导致多条查询结果
                        MsgBox("用户名非法输入！", MsgBoxStyle.OkOnly, "错误")

                    ElseIf dbTable.Rows.Count > 0 Then
                        If dbTable.Rows.Item(0).Item("是否启用") = True Then
                            Dim ulngLimit As UInt32 = CLng(User_ReadPublicValue("密码错误次数限制", "3"))
                            Dim ulngLockTime As UInt32 = CLng(User_ReadPublicValue("密码锁定时间", "10"))

                            Dim ulngErrorTimes As UInt32 = dbTable.Rows.Item(0).Item("错误次数")   '临时"错误次数"

                            If dbTable.Rows.Item(0).Item("错误次数") >= ulngLimit Then
                                If ulngLockTime > 0 Then
                                    '超过"密码锁定时间"分钟自动解锁定
                                    Dim ts As TimeSpan = Now() - CDate(dbTable.Rows.Item(0).Item("上次登录日期"))
                                    If ts.TotalMinutes < ulngLockTime Then
                                        MsgBox("输入密码错误次数过多！已被锁定，请" & CStr(ulngLockTime) & "分钟后再试，或联系管理员！",
                                               MsgBoxStyle.OkOnly, "错误")
                                    Else
                                        ulngErrorTimes = 0   '临时清空"错误次数"
                                    End If
                                Else
                                    MsgBox("输入密码错误次数过多！已被锁定，请联系管理员！", MsgBoxStyle.OkOnly, "错误")
                                End If
                            End If

                            If ulngErrorTimes < ulngLimit Then
                                If dbTable.Rows.Item(0).Item("密码") = strPassword Then

                                    strCmd = "UPDATE 用户管理 SET " & "错误次数=0" & " WHERE 用户名 = '" & strUserName & "'"
                                    dbCmd = New OleDbCommand(strCmd, g_dbConn用户设定)
                                    dbCmd.ExecuteNonQuery()

                                    strCmd = "UPDATE 用户管理 SET " & "上次登录日期=#" & Now() & "# WHERE 用户名 = '" & strUserName & "'"
                                    dbCmd = New OleDbCommand(strCmd, g_dbConn用户设定)
                                    dbCmd.ExecuteNonQuery()

                                    If Now().Date >= dbTable.Rows.Item(0).Item("密码到期日") Then
                                        MsgBox("密码到期，请修改密码！", MsgBoxStyle.OkOnly, "提示")
                                        SystemData.g_strUserName = strUserName
                                        ' TODO 显示修改密码Dialog
                                        Call New ChangePasswordWindow().ShowDialog()
                                        SystemData.g_strUserName = ""
                                    Else
                                        '当前登录用户的信息
                                        SystemData.g_strUserName = strUserName

                                        Dim strBuffer As String = ""
                                        strBuffer &= IIf(dbTable.Rows.Item(0).Item("泄漏检测权限"), "泄漏检测权限", "") & ", "
                                        strBuffer &= IIf(dbTable.Rows.Item(0).Item("添加产品权限"), "添加产品权限", "") & ", "
                                        strBuffer &= IIf(dbTable.Rows.Item(0).Item("编辑产品权限"), "编辑产品权限", "") & ", "
                                        strBuffer &= IIf(dbTable.Rows.Item(0).Item("通用设置权限"), "通用设置权限", "") & ", "
                                        strBuffer &= IIf(dbTable.Rows.Item(0).Item("用户管理权限"), "用户管理权限", "") & ", "
                                        strBuffer &= IIf(dbTable.Rows.Item(0).Item("记录管理权限"), "记录管理权限", "") & ", "
                                        strBuffer &= IIf(dbTable.Rows.Item(0).Item("日志管理权限"), "日志管理权限", "") & ", "
                                        strBuffer &= IIf(dbTable.Rows.Item(0).Item("报表打印导出权限"), "报表打印导出权限", "") & ", "
                                        strBuffer &= IIf(dbTable.Rows.Item(0).Item("报表模板管理权限"), "报表模板管理权限", "") & ", "

                                        SystemData.g_strUserLevel = strBuffer
                                        blnResult = True    '验证OK

                                    End If
                                Else
                                    strCmd = "UPDATE 用户管理 SET " & "错误次数=" & dbTable.Rows.Item(0).Item("错误次数") + 1 &
                                             " WHERE 用户名 = '" & strUserName & "'"
                                    dbCmd = New OleDbCommand(strCmd, g_dbConn用户设定)
                                    dbCmd.ExecuteNonQuery()

                                    strCmd = "UPDATE 用户管理 SET " & "上次登录日期=#" & Now() & "# WHERE 用户名 = '" & strUserName & "'"
                                    dbCmd = New OleDbCommand(strCmd, g_dbConn用户设定)
                                    dbCmd.ExecuteNonQuery()

                                    MsgBox("密码错误！", MsgBoxStyle.OkOnly, "错误")
                                End If

                            End If
                        Else
                            MsgBox("此用户已被禁用！", MsgBoxStyle.OkOnly, "错误")
                        End If
                    Else
                        MsgBox("用户名不存在！", MsgBoxStyle.OkOnly, "错误")
                    End If
                Catch ex As Exception
                    log.WriteLogError("CheckUser()", ex.Message)
                Finally
                    dbAdapter.Dispose()
                    dbAdapter = Nothing
                    dbTable = Nothing
                    dbCmd = Nothing
                End Try
            End If

            Return blnResult
        End Function


        '=====================================================================
        '函 数 名: CheckUserSimple
        '参    数: strUserName = 用户名
        '          strPassword = 密码
        '返 回 值: True = 验证OK
        '          False = 错误(用户名不存在，密码错误)
        '功能描述: 读取数据库，验证用户的正确性
        '=====================================================================
        Public Function CheckUserSimple(strUserName As String, strPassword As String) As Boolean
            If strUserName = "" Then
                log.WriteLogAssert("CheckUserSimple()", "strUserName=空")
                Return False
            End If

            If strPassword = "" Then
                log.WriteLogAssert("CheckUserSimple()", "strPassword=空")
                Return False
            End If

            Dim blnResult As Boolean = False

            If Not IsNothing(g_dbConn用户设定) Then
                Dim dbAdapter As New OleDbDataAdapter
                Dim dbTable As New DataTable

                Try
                    Dim strCmd As String = "SELECT * FROM 用户管理 WHERE 用户名 = '" & strUserName & "'"
                    dbAdapter = New OleDbDataAdapter(strCmd, g_dbConn用户设定) '打开数据库

                    dbAdapter.Fill(dbTable)

                    If dbTable.Rows.Count > 1 Then
                        '用户名异常，导致多条查询结果

                    ElseIf dbTable.Rows.Count > 0 Then
                        If dbTable.Rows.Item(0).Item("密码") = strPassword Then
                            blnResult = True    '验证OK
                        End If
                    End If
                Catch ex As Exception
                    log.WriteLogError("CheckUserSimple()", ex.Message)
                Finally
                    dbAdapter.Dispose()
                    dbAdapter = Nothing
                    dbTable = Nothing
                End Try
            End If

            Return blnResult
        End Function


        '=====================================================================
        '函 数 名: CheckUserExist
        '参    数: strUserName = 用户名
        '返 回 值: True = 验证OK
        '          False = 错误(用户名不存在)
        '功能描述: 读取数据库，验证用户的是否存在
        '=====================================================================
        Public Function CheckUserExist(strUserName As String) As Boolean
            If strUserName = "" Then
                log.WriteLogAssert("CheckUserExist()", "strUserName=空")
                Return False
            End If

            Dim blnResult As Boolean = False

            If Not IsNothing(g_dbConn用户设定) Then
                Dim dbAdapter As New OleDbDataAdapter
                Dim dbTable As New DataTable

                Try
                    Dim strCmd As String = "SELECT * FROM 用户管理 WHERE 用户名 = '" & strUserName & "'"
                    dbAdapter = New OleDbDataAdapter(strCmd, g_dbConn用户设定) '打开数据库

                    dbAdapter.Fill(dbTable)

                    If dbTable.Rows.Count > 1 Then
                        '用户名异常，导致多条查询结果

                    ElseIf dbTable.Rows.Count > 0 Then
                        blnResult = True    '验证OK
                    End If

                Catch ex As Exception
                    log.WriteLogDebug("CheckUserExist()", ex.Message)
                Finally
                    dbAdapter.Dispose()
                    dbAdapter = Nothing
                    dbTable = Nothing
                End Try
            End If

            Return blnResult
        End Function


        '=====================================================================
        '函 数 名: ReadOldPassword
        '参    数: strUserName = 用户名
        '返 回 值: [前3次密码]
        '功能描述: 读取数据库，用户的[前3次密码]
        '=====================================================================
        Public Function ReadOldPassword(strUserName As String) As String
            If strUserName = "" Then
                log.WriteLogAssert("ReadOldPassword()", "strUserName=空")
                Return False
            End If

            Dim strResult As String = ""

            If Not IsNothing(g_dbConn用户设定) Then
                Dim dbAdapter As New OleDbDataAdapter
                Dim dbTable As New DataTable

                Try
                    Dim strCmd As String = "SELECT * FROM 用户管理 WHERE 用户名 = '" & strUserName & "'"
                    dbAdapter = New OleDbDataAdapter(strCmd, g_dbConn用户设定) '打开数据库

                    dbAdapter.Fill(dbTable)

                    If dbTable.Rows.Count > 1 Then
                        '用户名异常，导致多条查询结果

                    ElseIf dbTable.Rows.Count > 0 Then
                        strResult = dbTable.Rows.Item(0).Item("前3次密码")    '验证OK
                    End If

                Catch ex As Exception
                    log.WriteLogDebug("ReadOldPassword()", ex.Message)
                Finally
                    dbAdapter.Dispose()
                    dbAdapter = Nothing
                    dbTable = Nothing
                End Try
            End If

            Return strResult
        End Function


        '=====================================================================
        '函 数 名: EditUserPassword
        '参    数: strUserName = 用户名
        '          strPassword = 密码
        '返 回 值: True = 验证OK
        '          False = 错误(用户名不存在，密码错误)
        '功能描述: 更新数据库，更新用户密码，提醒推迟30天
        '=====================================================================
        Public Function EditUserPassword(strUserName As String, strPassword As String) As Boolean
            If strUserName = "" Then
                log.WriteLogAssert("EditUserPassword()", "strUserName=空")
                Return False
            End If

            If strPassword = "" Then
                log.WriteLogAssert("EditUserPassword()", "strPassword=空")
                Return False
            End If

            Dim blnResult As Boolean = False

            If Not IsNothing(g_dbConn用户设定) Then
                Dim strCmd As String
                Dim dbCmd As New OleDbCommand

                Try
                    Dim strOldPassword As String = ReadOldPassword(SystemData.g_strUserName)

                    If strOldPassword <> "" Then
                        Dim strSplit() As String = Split(strOldPassword, ",")

                        If strSplit.Count > 2 Then
                            Dim i As Int16
                            strOldPassword = ""
                            For i = 1 To strSplit.Count - 1
                                strOldPassword &= strSplit(i) & ","
                            Next
                        End If
                    End If

                    strOldPassword &= "," & strPassword  '累积[前3次密码]

                    strCmd = "UPDATE 用户管理 SET " & "前3次密码 = '" & strOldPassword & "'" & " WHERE 用户名 = '" & strUserName & "'"
                    dbCmd = New OleDbCommand(strCmd, g_dbConn用户设定)
                    dbCmd.ExecuteNonQuery()

                    strCmd = "UPDATE 用户管理 SET " & "密码 = '" & strPassword & "'" & " WHERE 用户名 = '" & strUserName & "'"
                    dbCmd = New OleDbCommand(strCmd, g_dbConn用户设定)
                    dbCmd.ExecuteNonQuery()

                    Dim ulngDay As UInt32 = CLng(User_ReadPublicValue("密码更换周期", "60"))

                    strCmd = "UPDATE 用户管理 SET " & "密码到期日=#" & CDate(Now() + New TimeSpan(ulngDay, 0, 0, 0)) &
                             "# WHERE 用户名 = '" & strUserName & "'"
                    dbCmd = New OleDbCommand(strCmd, g_dbConn用户设定)
                    dbCmd.ExecuteNonQuery()

                    log.WriteLogInfo("修改密码", "用户名=" & strUserName)

                Catch ex As Exception
                    log.WriteLogError("EditUserPassword()", ex.Message)
                Finally
                    dbCmd = Nothing
                End Try
            End If

            Return blnResult
        End Function


        '=====================================================================
        '函 数 名: Template_ReadRecordTemplate
        '参    数: pdbTable   = 读取到的数据表
        '返 回 值: 是否成功
        '          True  = 读取成功
        '          False = 读取失败
        '功能描述: 读取[模板管理.mdb]的[测试记录模板]
        '=====================================================================
        Public Function Template_ReadRecordTemplate(ByRef pdbTable As DataTable) As Boolean
            Dim blnOK As Boolean = False

            If Not IsNothing(Database.g_dbConn模板管理) Then
                Dim strCmd As String = "SELECT * FROM 测试记录模板"

                Dim dbAdapter As New OleDbDataAdapter
                Dim dbTable As New DataTable

                Try
                    dbAdapter = New OleDbDataAdapter(strCmd, g_dbConn模板管理) '打开数据库

                    dbAdapter.Fill(dbTable) '提取数据
                    'pdbTable = dbTable.Clone()
                    pdbTable = dbTable.Copy()

                    blnOK = True
                Catch ex As Exception
                    log.WriteLogDebug("Template_ReadRecordTemplate():" & strCmd, ex.Message)
                Finally
                    dbAdapter.Dispose()
                    dbTable = Nothing
                    dbAdapter = Nothing
                End Try

            End If

            Return blnOK
        End Function
    End Module
End Namespace